package com.example.springbootjackson.model;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;

@Slf4j
public class Test {
	/**
	 * 需要压缩的文件夹
	 */
	private final static String downloadDir = "download";
	/**
	 * 打包后的文件夹
	 */
	private final static String downloadZip = "downloadZip";

	/**
	 * 通过图片url下载图片到指定文件夹
	 * @param downloadUrl	图片url
	 */
	public void downloadFile(String downloadUrl) {
		InputStream inputStream = null;
		OutputStream outputStream = null;
		try {
			//获取连接
	        URL url=new URL(downloadUrl);
	        HttpURLConnection connection=(HttpURLConnection)url.openConnection();
	        connection.setConnectTimeout(5*1000);
	        //设置请求头
	        connection.setRequestProperty("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.110 Safari/537.36");
	        //获取输入流
	        inputStream=connection.getInputStream();

	        File fileDir=new File(downloadDir);
			if(!fileDir.exists()){
				fileDir.mkdir();
			}

	        //截取文件名称，可以把 / 换成需要的规则
	        String filePath = downloadDir+"/" + downloadUrl.substring(downloadUrl.lastIndexOf("/"));
	        File file = new File(filePath);
			//创建文件，存在覆盖
			log.info("fileName={}, create={}", file.getName(), file.createNewFile());

			outputStream = new FileOutputStream(file);
			int len = 0;
			byte[] buf = new byte[1024];
			while ((len = inputStream.read(buf, 0, 1024)) != -1) {
				outputStream.write(buf, 0, len);
			}
			outputStream.flush();
		} catch (Exception e) {
			log.error("文件下载出错：" + e);
		} finally {
			IOUtils.closeQuietly(outputStream);
			IOUtils.closeQuietly(inputStream);
		}
	}


    /**
     * 下载压缩包
     */
	public void downloadZip(HttpServletRequest request,HttpServletResponse res, String zipName) throws IOException {
		OutputStream out = null;
		File zip = null;
		BufferedInputStream bis = null;
		try{
	    	//多个文件进行压缩，批量打包下载文件
		    //创建压缩文件需要的空的zip包
		    String zipFilePath = downloadZip+File.separator+zipName;

		    File fileDir=new File(downloadZip);
			if(!fileDir.exists()){
				fileDir.mkdir();
			}

		    //压缩文件
		    zip = new File(zipFilePath);
			//创建文件，存在覆盖
			log.info("fileName={}, create={}", zip.getName(), zip.createNewFile());

			//IO流实现下载的功能
			//设置编码字符
			res.setCharacterEncoding("UTF-8");
			//设置下载内容类型application/octet-stream（二进制流，未知文件类型）；
			res.setContentType("application/octet-stream;charset=UTF-8");

			//防止文件名乱码
			String userAgent = request.getHeader("USER-AGENT");
			//火狐浏览器
			if (userAgent.contains("Firefox") || userAgent.contains("firefox")) {
				zipName = new String(zipName.getBytes(), "ISO8859-1");
			} else {
				//其他浏览器
				zipName = URLEncoder.encode(zipName, "UTF-8");
			}

			//设置下载的压缩文件名称
			res.setHeader("Content-disposition", "attachment;filename="+zipName);
			//创建页面返回方式为输出流，会自动弹出下载框
			out = res.getOutputStream();

		    //创建zip文件输出流
	        ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip));
		    this.zipFile(downloadDir, zos);
		    zos.close();

		    //将打包后的文件写到客户端，输出的方法同上，使用缓冲流输出
		    bis = new BufferedInputStream(new FileInputStream(zipFilePath));
//		    byte[] buff = new byte[bis.available()];
//		    bis.read(buff);
//			//输出数据文件
//		    out.write(buff);
			try {
				byte [] buffer = new byte[1000];
				int count = 0;
				while ((count = bis.read(buffer)) > 0) {
		    		out.write(buffer, 0 , count);
				}
			} catch (IOException e) {  }


	    }catch(Exception e) {
	    	log.error("压缩包下载出错：" + e);
		}finally {
			IOUtils.closeQuietly(bis);
			if(out != null){
				out.flush();//释放缓存
				out.close();//关闭输出流
			}

			//下载完后删除文件夹和压缩包
			File fileDir = new File(downloadDir);
			FileUtils.deleteDirectory(fileDir);

			if(zip != null){
				log.info("zip delete={}", zip.delete());
			}
		}
	}

	public static void main(String[] args) {
		String rootPath = System.getProperty("java.io.tmpdir");
		System.out.println(rootPath);
	}

	/**
	 * 压缩文件
	 * @param filePath	需要压缩的文件夹
	 * @param zos	zip文件输出流
	 */
	private void zipFile(String filePath,ZipOutputStream zos) throws IOException {
        File inputFile = new File(filePath);
        if(inputFile.exists()) {
            if (inputFile.isFile()) {
				BufferedInputStream bis = null;
            	try {
					//创建输入流读取文件
					bis = new BufferedInputStream(new FileInputStream(inputFile));

					//将文件写入zip内，即将文件进行打包
					zos.putNextEntry(new ZipEntry(inputFile.getName()));

					//写入文件的方法，同上
					int size = 0;
					//设置读取数据缓存大小
					byte[] buffer = new byte[1024];
					while ((size = bis.read(buffer)) > 0) {
						zos.write(buffer, 0, size);
					}

				}catch (Exception e) {

				}finally {
					//关闭输入输出流
					IOUtils.closeQuietly(zos);
					IOUtils.closeQuietly(bis);
				}


            } else {  //如果是文件夹，则使用穷举的方法获取文件，写入zip
                try {
                    File[] files = inputFile.listFiles();
                    for (File fileTem:files) {
                    	zipFile(fileTem.toString(),zos);
                    }
                } catch (Exception e) {
                	log.error("压缩文件出错：" + e);
                }
            }
        }
	}
}
